package display.test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class ColorGradientDemo extends JComponent {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private BufferedImage image = null;

	public static void main(String[] args) {
		JFrame frame = new JFrame("Gradient Color Panel");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(new BorderLayout());
		
		frame.getContentPane().add(new ColorGradientDemo(), BorderLayout.CENTER);
		frame.setPreferredSize(new Dimension(280, 305));
		frame.pack();
		frame.setVisible(true);
	}

	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2.drawImage(getImage(1), 5, 5, image.getWidth(), image.getHeight(), null);
	}

	private Image getImage(int type) {
		if (image == null) {
			image = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
			int[] rgbData = new int[256 * 256];
			if (type == 1)
				generateVGradientImage(rgbData);
			else if (type == 2)
				generateHGradientImage(rgbData);
			else
				generateHVGradientImage(rgbData);
			setRGB(image, 0, 0, 256, 256, rgbData);
		}
		return image;
	}

	private void setRGB(BufferedImage image, int x, int y, int width, int height, int[] pixels) {
		int type = image.getType();
		if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB)
			image.getRaster().setDataElements(x, y, width, height, pixels);
		else
			image.setRGB(x, y, width, height, pixels, 0, width);
	}

	private void generateHVGradientImage(int[] rgbData) {
		int[] startColor = getStartColor();
		int[] endColor = getEndColor();
		
		float rr = startColor[0] - endColor[0];
		float gg = startColor[1] - endColor[1];
		float bb = startColor[2] - endColor[2];
		
		int a = 255;
		int r = 0, g = 0, b = 0;
		int index = 0;
		float size = (float) Math.pow(255.0d, 2.0);
		for (int row = 0; row < 256; row++) {
			for (int col = 0; col < 256; col++) {
				r = endColor[0] + (int)(rr * (((float)col * (float)row) / size) + 0.5f);
				g = endColor[1] + (int)(gg * (((float)col * (float)row) / size) + 0.5f);
				b = endColor[2] + (int)(bb * (((float)col * (float)row) / size) + 0.5f);
				
				rgbData[index] = ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff));
				index++;
			}
		}
	}

	private void generateHGradientImage(int[] rgbData) {
		int[] startColor = getStartColor();
		int[] endColor = getEndColor();
		
		float rr = startColor[0] - endColor[0];
		float gg = startColor[1] - endColor[1];
		float bb = startColor[2] - endColor[2];
		
		int a = 255;
		int r = 0, g = 0, b = 0;
		int index = 0;
		for (int row = 0; row < 256; row++) {
			for (int col = 0; col < 256; col++) {
				r = endColor[0] + (int)(rr * ((float)col / 255.0f) + 0.5f);
				g = endColor[1] + (int)(gg * ((float)col / 255.0f) + 0.5f);
				b = endColor[2] + (int)(bb * ((float)col / 255.0f) + 0.5f);
				
				rgbData[index] = ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff));
				index++;
			}
		}
	}

	private void generateVGradientImage(int[] rgbData) {
		int[] startColor = getStartColor();
		int[] endColor = getEndColor();
		
		float rr = startColor[0] - endColor[0];
		float gg = startColor[1] - endColor[1];
		float bb = startColor[2] - endColor[2];
		
		int a = 255;
		int r = 0, g = 0, b = 0;
		int index = 0;
		for (int row = 0; row < 256; row++) {
			for (int col = 0; col < 256; col++) {
				r = endColor[0] + (int)(rr * ((float)row / 255.0f) + 0.5f);
				g = endColor[1] + (int)(gg * ((float)row / 255.0f) + 0.5f);
				b = endColor[2] + (int)(bb * ((float)row / 255.0f) + 0.5f);
				
				rgbData[index] = ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff));
				index++;
			}
		}
	}

	private int[] getEndColor() {
		return new int[]{0, 255, 255};
	}

	private int[] getStartColor() {
		return new int[]{246, 53, 138};
	}

	
}